﻿using System;
using System.Web;
using System.Web.Hosting;
using System.IO;

namespace Medianamik.Core.HttpHandlers
{
    public class MedianamikStaticContentHandler : IHttpHandler
    {
        private static readonly string AssemblyTag = Guid.NewGuid().ToString("N");

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            var provider = HostingEnvironment.VirtualPathProvider;
            var filePath = context.Request.FilePath;

            if (provider.FileExists(filePath))
            {
                var etag = GenerateETag(filePath);

                if (context.Request.Headers["If-None-Match"] == etag)
                {
                    Response304(context); 
                }
                else
                {
                    Response200(filePath,etag, context);
                }
            }
            else
            {
                Response404(context );
            }
        }

        private void Response404(HttpContext context)
        {
            context.Response.Clear();
            context.Response.StatusCode = 404;
            context.Response.StatusDescription = "Not Found";
            context.Response.End();
        }

        private void Response304(HttpContext context)
        {
            context.Response.Clear();
                    context.Response.StatusCode = 304;
                    context.Response.StatusDescription = "Not Modified";
                    context.Response.End();
        }

        private void Response200(string filePath, string etag, HttpContext context)
        {
            context.Response.Clear();
            context.Response.ContentType = GetContentType(filePath);
            context.Response.Headers["ETag"] = etag;

            using (var stream = HostingEnvironment.VirtualPathProvider.GetFile(filePath).Open())
            {
                var bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                context.Response.OutputStream.Write(bytes, 0, bytes.Length);
            }

            context.Response.End();
        }

        /// <summary>
        /// Génère un ETag pour ajouter aux Headers de la réponse.
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private string GenerateETag(string filePath)
        {
            //TODO: Rendre de ETag dépendant de la version de l'assembly
            return "\"" + AssemblyTag + filePath.GetHashCode() + "\"";
        }

        private string GetContentType(string pVirtualPath)
        {
            string contentType;

            switch (Path.GetExtension(pVirtualPath).ToLower())
            {
                case ".gif":
                    contentType = "image/gif";
                    break;
                case ".jpg":
                case ".jpeg":
                    contentType = "image/jpeg";
                    break;
                case ".png":
                    contentType = "image/png";
                    break;
                case ".css":
                    contentType = "text/css";
                    break;
                case ".js":
                    contentType = "application/x-javascript";
                    break;
		        default:
                    contentType =  "";
                     break;
            }

            return contentType;
             
        }
    }
}